import os
import logging

# ===CODE===

def path_join(*args) -> str:
    '''把args中的所以路径用"/"连接起来
    【注意】会去除路径结尾的"/"，且不检查路径的合法性'''
    # 不使用os.path.join的原因是在windows系统下join产生的路径带有"\"，经常造成转意错误
    # 在windows下使用cygwin可以统一当做UNIX环境
    ret = ''
    for arg in args:
        ret += arg
        if ret[-1] != '/':
            ret += '/'
    ret = ret[:-1]
    return ret


class FileLists:
    '''保存各个项目中的src和mgc的文件名'''
    def __init__(self):
        self.data = {}          # {proj_name : data_item}
        self.inc_idx = 0        # <proj>/inc/*
        self.src_idx = 1        # <proj>/src/*
        self.mgc_idx = 2        # <proj>/mgc/*
        self.mgc_inc_idx = 3    # <out_dir>/mgc/<proj>/inc/*
        self.mgc_src_idx = 4    # <out_dir>/mgc/<proj>/src/*
        self.src_dir_idx = 5    # src/mgc_src/remote_src中的目录名称，相对src的路径，obj目录结构与src保持一致时使用
    
    def __gen_data_item(self):
        return [[], [], [], [], [], []]

    def set_inc_files(self, proj_name:str, inc_file_names:list):
        for name in inc_file_names:
            self.__check_file_name(name)
        if proj_name not in self.data:
            self.data[proj_name] = self.__gen_data_item()
        self.data[proj_name][self.inc_idx] = inc_file_names

    def get_inc_files(self, proj_name:str) -> list:
        '''不存在时返回空list'''
        if proj_name in self.data:
            return self.data[proj_name][self.inc_idx]
        return []

    def set_src_files(self, proj_name:str, src_file_names:list):
        '''设置项目src目录下的文件（可能含义源文件以外的文件）'''
        for name in src_file_names:
            self.__check_file_name(name)
        if proj_name not in self.data:
            self.data[proj_name] = self.__gen_data_item()
        self.data[proj_name][self.src_idx] = src_file_names

    def get_src_files(self, proj_name:str) -> list:
        '''获取项目src目录下的文件（可能含义源文件以外的文件）
        Return: 不存在时返回空list'''
        if proj_name in self.data:
            return self.data[proj_name][self.src_idx]
        return []

    def set_mgc_files(self, proj_name:str, mgc_file_names:list):
        '''设置用于生成代码的文件'''
        for name in mgc_file_names:
            self.__check_file_name(name)
        if proj_name not in self.data:
            self.data[proj_name] = self.__gen_data_item()
        self.data[proj_name][self.mgc_idx] = mgc_file_names

    def get_mgc_files(self, proj_name:str) -> list:
        '''不存在时返回空list'''
        if proj_name in self.data:
            return self.data[proj_name][self.mgc_idx]
        return []

    def set_mgc_inc_files(self, proj_name:str, mgc_inc_file_names:list):
        if proj_name not in self.data:
            self.data[proj_name] = self.__gen_data_item()
        self.data[proj_name][self.mgc_inc_idx] = mgc_inc_file_names

    def get_mgc_inc_files(self, proj_name:str):
        '''不存在时返回空list'''
        if proj_name in self.data:
            return self.data[proj_name][self.mgc_inc_idx]
        return []

    def set_mgc_src_files(self, proj_name:str, mgc_src_file_names:list):
        if proj_name not in self.data:
            self.data[proj_name] = self.__gen_data_item()
        self.data[proj_name][self.mgc_src_idx] = mgc_src_file_names

    def get_mgc_src_files(self, proj_name:str):
        '''不存在时返回空list'''
        if proj_name in self.data:
            return self.data[proj_name][self.mgc_src_idx]
        return []

    def append_src_inner_dirs(self, proj_name, inner_dirs):
        '''设置项目的src和mgc/src内部的所有目录（用于创建产出Obj目录的目录结构）'''
        if proj_name not in self.data:
            self.data[proj_name] = self.__gen_data_item()
        self.data[proj_name][self.src_dir_idx].extend(inner_dirs)

    def get_src_inner_dirs(self, proj_name):
        '''不存在时返回空list'''
        if proj_name in self.data:
            return self.data[proj_name][self.src_dir_idx]
        return []

    def __check_file_name(self, file_name):
        '''检查文件名的合法性，不可以包含空格'''
        if file_name.find(' ') != -1:
            errorExit('illegal file name: %s'%(file_name))

# 把字符串列表l中的字符串拼接成一个字符串并返回
def str_list_to_str(l:list) -> str:
    ret = ''
    for s in l:
        ret += s
    return ret

def errorExit(msg:str) :
    logging.error(msg)
    exit(1)

class SimpleMakeError(Exception):
    def __init__(self, message=''):
        super().__init__(message)
        self.message = message

def get_dir_files(dir_name:str)->list:
    '''获取目录内的所有文件（递归，完整路径）'''
    ret_files = []
    for root, _, files in os.walk(dir_name):
        for file in files:
            ret_files.append(path_join(root, file))
    return ret_files

def get_dir_dirs(dir_name:str)->list:
    '''获取目录内的所有目录（递归，相对dir_name的路径）
    【注意】dir_name不可以以"/"结尾'''
    ret_dirs = []
    header_length = len(dir_name) + 1
    for root, dirs, _ in os.walk(dir_name):
        for dir in dirs:
            name = path_join(root, dir)
            name = name[header_length:]
            ret_dirs.append(name)
    return ret_dirs

def get_files_mtime(file_names:list) -> dict:
    ret = {}
    for file_name in file_names:
        ret[file_name] = os.stat(file_name).st_mtime
    return ret
